home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / SHDK_1 / SHLIST.PAS < prev    next >
Pascal/Delphi Source File  |  1992-03-24  |  22KB  |  666 lines

  1. {$O+,A-,V-}
  2. unit ShList;
  3. {
  4.                                  ShList
  5.  
  6.                          A List Processing Unit
  7.  
  8.                                    by
  9.  
  10.                               Bill Madison
  11.  
  12.                    W. G. Madison and Associates, Ltd.
  13.                           13819 Shavano Downs
  14.                             P.O. Box 780956
  15.                        San Antonio, TX 78278-0956
  16.                              (512)492-2777
  17.                              CIS 73240,342
  18.  
  19.                   Copyright 1991 Madison & Associates
  20.                           All Rights Reserved
  21.  
  22.         This file may  be used and distributed  only in accord-
  23.         ance with the provisions described on the title page of
  24.                   the accompanying documentation file
  25.                               SKYHAWK.DOC
  26. }
  27.  
  28. interface
  29.  
  30. uses
  31.   TpString,
  32.   TpInline,
  33.   TpMemChk;
  34.  
  35. type
  36.   slNodePtr = ^slNode;
  37.   slNode    = record
  38.                 Data  : pointer;
  39.                 Next  : slNodePtr;
  40.                 end;
  41.   dlNodePtr = ^dlNode;
  42.   dlNode    = record
  43.                 Data  : pointer;
  44.                 Next,
  45.                 Prev  : dlNodePtr;
  46.                 end;
  47.   slList    = record
  48.                 DataRecSize : word;
  49.                 Count       : LongInt;
  50.                 Head,
  51.                 Tail,
  52.                 Current     : slNodePtr;
  53.                 end;
  54.   dlList    = record
  55.                 DataRecSize : word;
  56.                 Count       : LongInt;
  57.                 Head,
  58.                 Tail,
  59.                 Current     : dlNodePtr;
  60.                 end;
  61.   dlLessFunc= function(var DataRec1, DataRec2)  : boolean;
  62.  
  63. {******************INITIALIZATION ROUTINES************************}
  64.  
  65. procedure slListInit(var L  : slList; RecSize : word);
  66. {Initializes a singly linked list.}
  67.  
  68. procedure dlListInit(var L : dlList; RecSize : word);
  69. {Initializes a doubly linked list.}
  70.  
  71. {******************STORAGE ROUTINES************************}
  72.  
  73. function slPush(var L : slList; var DataRec) : boolean;
  74. function dlPush(var L : dlList; var DataRec) : boolean;
  75. {Pushes a data record onto the top of the list.}
  76.  
  77. function slAppend(var L : slList; var DataRec) : boolean;
  78. function dlAppend(var L : dlList; var DataRec) : boolean;
  79. {Appends a data record to the tail of the list.}
  80.  
  81. function slPut(var L : slList; var DataRec) : boolean;
  82. function dlPut(var L : dlList; var DataRec) : boolean;
  83. {Inserts a data record following the current node; returns with current
  84.  pointer directed to the new node.}
  85.  
  86. function dlPutPrev(var L : dlList; var DataRec) : boolean;
  87. {Inserts a data record ahead of the current node; returns with current
  88.  pointer directed to the new node.}
  89.  
  90. function dlPutSorted(var L : dlList;
  91.                         var DataRec; Less : dlLessFunc) : boolean;
  92. {Inserts a data record into the list in sorted order, as determined by
  93.  the user-defined boolean function LESS.}
  94.  
  95. procedure slFree(var L : slList);
  96. procedure dlFree(var L : dlList);
  97. {Releases the heap space allocated for a list and re-initializes the
  98.  list.}
  99.  
  100. {******************RETRIEVAL ROUTINES************************}
  101.  
  102. function slGetCurrent(var L : slList; var DataRec) : boolean;
  103. {Returns the data record at the current node and does not move the node
  104.  pointer. Returns a function value of false if the list is empty or the
  105.  current node pointer is nil.}
  106.  
  107. function dlGetCurrent(var L : dlList; var DataRec) : boolean;
  108. {Returns the data record at the current node and does not move the node
  109.  pointer. Returns a function value of false if the list is empty or the
  110.  current node pointer is nil.}
  111.  
  112. function slGetFirst(var L : slList; var DataRec) : boolean;
  113. {Returns the data record at the head of the list. Sets the current node
  114.  pointer to the head of the list. Returns a function value of false if
  115.  the list is empty.}
  116.  
  117. function dlGetFirst(var L : dlList; var DataRec) : boolean;
  118. {Returns the data record at the head of the list. Sets the current node
  119.  pointer to the head of the list. Returns a function value of false if
  120.  the list is empty.}
  121.  
  122. function slGetLast(var L : slList; var DataRec) : boolean;
  123. {Returns the data record at the tail of the list. Sets the current node
  124.  pointer to the tail of the list. Returns a function value of false if
  125.  the list is empty.}
  126.  
  127. function dlGetLast(var L : dlList; var DataRec) : boolean;
  128. {Returns the data record at the tail of the list. Sets the current node
  129.  pointer to the tail of the list. Returns a function value of false if
  130.  the list is empty.}
  131.  
  132. function slGetNext(var L : slList; var DataRec) : boolean;
  133. {Returns the next data record in the list. Sets the current node pointer
  134.  to the record retrieved. Returns a function value of false if the list is
  135.  empty or if the last record successfully retrieved was at the list tail.
  136.  In this case, calling slGetNext again will retrieve the head of the list.}
  137.  
  138. function dlGetNext(var L : dlList; var DataRec) : boolean;
  139. {Returns the next data record in the list. Sets the current node pointer
  140.  to the record retrieved. Returns a function value of false if the list is
  141.  empty or if the last record successfully retrieved was at the list tail.
  142.  In this case, calling dlGetNext again will retrieve the head of the list.}
  143.  
  144. function dlGetPrev(var L : dlList; var DataRec) : boolean;
  145. {Same as dlGetNext, but in the opposite direction.}
  146.  
  147. function slPop(var L : slList; var DataRec) : boolean;
  148. {Returns the data record at the head of the list, then deallocates the
  149.  space associated with the data record and node. Returns a function value
  150.  of false if the list is empty.}
  151.  
  152. function dlPop(var L : dlList; var DataRec) : boolean;
  153. {Returns the data record at the head of the list, then deallocates the
  154.  space associated with the data record and node. Returns a function value
  155.  of false if the list is empty.}
  156.  
  157. {******************GENERAL UTILITY ROUTINES************************}
  158.  
  159. function slCount(L : slList) : LongInt;
  160. {Returns the number of records currently in the list.}
  161.  
  162. function dlCount(L : dlList) : LongInt;
  163. {Returns the number of records currently in the list.}
  164.  
  165. function slSpaceUsed(L : slList) : LongInt;
  166. {Returns the total amount of heap space currently allocated to the list.}
  167.  
  168. function dlSpaceUsed(L : dlList) : LongInt;
  169. {Returns the total amount of heap space currently allocated to the list.}
  170.  
  171. function Ptr2Str(P : pointer) : string;
  172. {This function is included primarily for debugging.}
  173. {Returns a string of the form ssss:oooo being the hex representation of
  174.  the pointer P following normalization, in segment:offset form.}
  175.  
  176. {*******************************************************************}
  177. {*******************************************************************}
  178. implementation
  179. {*******************************************************************}
  180. {*******************************************************************}
  181.  
  182. {******************INTERNAL UTILITY ROUTINES************************}
  183.  
  184. function Ptr2Str(P:pointer) : string; {For debugging only!}
  185.   begin
  186.     Ptr2Str := HexPtr(Normalized(P));
  187.     end;
  188.  
  189. function slGrabMemory(var L : slList;
  190.                       var P : slNodePtr;
  191.                       var DataRec)        : boolean;
  192. {Gets the heap space needed for the node and its data record.}
  193.   begin
  194.     if GetMemCheck(P, SizeOf(slNode)) then begin
  195.       if GetMemCheck(P^.Data, L.DataRecSize) then begin
  196.         slGrabMemory := true;
  197.         Move(DataRec, P^.Data^, L.DataRecSize);
  198.         exit;
  199.         end
  200.       else {room for the node but not the data}
  201.         FreeMemCheck(P, SizeOf(slNode));
  202.       end;
  203.     {If we get to here, there has been a space allocation problem.}
  204.     slGrabMemory := false;
  205.     end;  {slGrabMemory}
  206.  
  207. function dlGrabMemory(var L : dlList;
  208.                       var P : dlNodePtr;
  209.                       var DataRec)        : boolean;
  210. {Gets the heap space needed for the node and its data record.}
  211.   begin
  212.     if GetMemCheck(P, SizeOf(dlNode)) then begin
  213.       if GetMemCheck(P^.Data, L.DataRecSize) then begin
  214.         dlGrabMemory := true;
  215.         Move(DataRec, P^.Data^, L.DataRecSize);
  216.         exit;
  217.         end
  218.       else {room for the node but not the data}
  219.         FreeMemCheck(P, SizeOf(dlNode));
  220.       end;
  221.     {If we get to here, there has been a space allocation problem.}
  222.     dlGrabMemory := false;
  223.     end;  {dlGrabMemory}
  224.  
  225. function slFirstNode(var L : slList; var P : slNodePtr) : boolean;
  226. {If list L is empty and the first node has been allocated, sets up the
  227.  pointers. Assumes that the node has been allocated with slGrabMemory.
  228.  Returns a function value of false if the list is not empty.}
  229.   begin
  230.     L.Current := P;
  231.     if L.Count = 0 then begin
  232.       slFirstNode := true;
  233.       P^.Next := nil;
  234.       L.Head := P;
  235.       L.Tail := P;
  236.       end
  237.     else
  238.       slFirstNode := false;
  239.     end; {slFirstNode}
  240.  
  241. function dlFirstNode(var L : dlList; var P : dlNodePtr) : boolean;
  242. {If list L is empty and the first node has been allocated, sets up the
  243.  pointers. Assumes that the node has been allocated with dlGrabMemory.
  244.  Returns a function value of false if the list is not empty.}
  245.   var
  246.     B1  : boolean;
  247.   begin
  248.     B1 := slFirstNode(slList(L), slNodePtr(P));
  249.     if B1 then
  250.       P^.Prev := nil;
  251.     dlFirstNode := B1;
  252.     end; {dlFirstNode}
  253.  
  254. {******************INITIALIZATION ROUTINES************************}
  255.  
  256. procedure slListInit(var L  : slList; RecSize : word);     
  257. {Initializes a singly linked list.}
  258.   begin
  259.     with L do begin
  260.       DataRecSize := RecSize;
  261.       Count := 0;
  262.       Head := nil;
  263.       Tail := nil;
  264.       Current := nil;
  265.       end; {with}
  266.     end; {slListInit}
  267.  
  268. procedure dlListInit(var L : dlList; RecSize : word);
  269. {Initializes a doubly linked list.}
  270.   begin
  271.     slListInit(slList(L), RecSize);
  272.     end; {dlListInit}
  273.  
  274. {******************STORAGE ROUTINES************************}
  275.  
  276. function slPush(var L : slList; var DataRec) : boolean;
  277. {Pushes a data record onto the top of the list.}
  278.   var
  279.     P : slNodePtr;
  280.   begin
  281.     if not slGrabMemory(L, P, DataRec) then begin
  282.       slPush := false;
  283.       exit;
  284.       end;
  285.     slPush := true;
  286.     if not slFirstNode(L, P) then begin
  287.       P^.Next := L.Head;
  288.       L.Head := P;
  289.       end;
  290.     inc(L.Count);
  291.     end; {slPush}
  292.  
  293. function dlPush(var L : dlList; var DataRec) : boolean;
  294. {Pushes a data record onto the top of the list.}
  295.   var
  296.     P : dlNodePtr;
  297.   begin
  298.     if not dlGrabMemory(L, P, DataRec) then begin
  299.       dlPush := false;
  300.       exit;
  301.       end;
  302.     dlPush := true;
  303.     if not dlFirstNode(L, P) then begin
  304.       P^.Next := L.Head;
  305.       L.Head^.Prev := P;
  306.       L.Head := P;
  307.       L.Head^.Prev := nil;
  308.       end;
  309.     inc(L.Count);
  310.     end; {dlPush}
  311.  
  312. function slAppend(var L : slList; var DataRec) : boolean;
  313. {Appends a data record to the tail of the list.}
  314.   var
  315.     P : slNodePtr;
  316.   begin
  317.     if not slGrabMemory(L, P, DataRec) then begin
  318.       slAppend := false;
  319.       exit;
  320.       end;
  321.     slAppend := true;
  322.     if not slFirstNode(L, P) then begin
  323.       L.Tail^.Next := P;
  324.       L.Tail := P;
  325.       L.Tail^.Next := nil;
  326.       end;
  327.     inc(L.Count);
  328.     end; {slAppend}
  329.  
  330. function dlAppend(var L : dlList; var DataRec) : boolean;
  331. {Appends a data record to the tail of the list.}
  332.   var
  333.     P : dlNodePtr;
  334.   begin
  335.     if not dlGrabMemory(L, P, DataRec) then begin
  336.       dlAppend := false;
  337.       exit;
  338.       end;
  339.     dlAppend := true;
  340.     if not dlFirstNode(L, P) then begin
  341.       L.Tail^.Next := P;
  342.       P^.Prev := L.Tail;
  343.       L.Tail := P;
  344.       L.Tail^.Next := nil;
  345.       end;
  346.     inc(L.Count);
  347.     end; {dlAppend}
  348.  
  349. function slPut(var L : slList; var DataRec) : boolean;
  350. {Inserts a data record following the current node; returns with current
  351.  pointer directed to the new node.}
  352.   var
  353.     P,
  354.     C : slNodePtr;
  355.   begin
  356.     if not slGrabMemory(L, P, DataRec) then begin
  357.       slPut := false;
  358.       exit;
  359.       end;
  360.     slPut := true;
  361.     C := L.Current;
  362.     if not slFirstNode(L, P) then begin
  363.       L.Current^.Next := C^.Next;
  364.       C^.Next := L.Current;
  365.       end;
  366.     if L.Current^.Next = nil then
  367.       L.Tail := L.Current;
  368.     inc(L.Count);
  369.     end; {slPut}
  370.  
  371. function dlPut(var L : dlList; var DataRec) : boolean;
  372. {Inserts a data record following the current node; returns with current
  373.  pointer directed to the new node.}
  374.   var
  375.     P,
  376.     C : dlNodePtr;
  377.   begin
  378.     if not dlGrabMemory(L, P, DataRec) then begin
  379.       dlPut := false;
  380.       exit;
  381.       end;
  382.     dlPut := true;
  383.     C := L.Current;
  384.     if not dlFirstNode(L, P) then begin
  385.       L.Current^.Next := C^.Next;
  386.       C^.Next := L.Current;
  387.       L.Current^.Prev := C;
  388.       L.Current^.Next^.Prev := L.Current;
  389.       end;
  390.     if L.Current^.Next = nil then
  391.       L.Tail := L.Current;
  392.     inc(L.Count);
  393.     end; {dlPut}
  394.  
  395. function dlPutPrev(var L : dlList; var DataRec) : boolean;
  396. {Inserts a data record ahead of the current node; returns with current
  397.  pointer directed to the new node.}
  398.   var
  399.     P,
  400.     C : dlNodePtr;
  401.   begin
  402.     if not dlGrabMemory(L, P, DataRec) then begin
  403.       dlPutPrev := false;
  404.       exit;
  405.       end;
  406.     dlPutPrev := true;
  407.     C := L.Current;
  408.     if not dlFirstNode(L, P) then begin
  409.       L.Current^.Prev := C^.Prev;
  410.       C^.Prev := L.Current;
  411.       L.Current^.Next := C;
  412.       L.Current^.Prev^.Next := L.Current;
  413.       end;
  414.     if L.Current^.Prev = nil then
  415.       L.Head := L.Current;
  416.     inc(L.Count);
  417.     end; {dlPutPrev}
  418.  
  419. function dlPutSorted(var L : dlList;
  420.                         var DataRec; Less : dlLessFunc) : boolean;
  421. {Inserts a data record into the list in sorted order, as determined by
  422.  the user-defined boolean function LESS.}
  423.   var
  424.     DataRec0  : pointer;
  425.   begin
  426.     if L.Count = 0 then begin                 {Empty list}
  427.       dlPutSorted := dlPut(L, DataRec);
  428.       exit;
  429.       end;
  430.     if not GetMemCheck(DataRec0, L.DataRecSize) then begin
  431.       dlPutSorted := false;
  432.       exit;
  433.       end;
  434.     if not dlGetCurrent(L, DataRec0^) then begin
  435.       if dlGetLast(L, DataRec0^) then ;
  436.       if Less(DataRec0^, DataRec) then begin
  437.         dlPutSorted := dlAppend(L, DataRec);
  438.         FreeMemCheck(DataRec0, L.DataRecSize);
  439.         exit;
  440.         end;
  441.       if dlGetFirst(L, DataRec0^) then ;
  442.       if not Less(DataRec0^, DataRec) then begin
  443.         dlPutSorted := dlPush(L, DataRec);
  444.         FreeMemCheck(DataRec0, L.DataRecSize);
  445.         exit;
  446.         end;
  447.       end; {if not dlGetCurrent}
  448.     if Less(DataRec0^, DataRec) then begin
  449.       while dlGetNext(L, DataRec0^) and Less(DataRec0^, DataRec) do ;
  450.       if not Less(DataRec0^, DataRec) then begin
  451.         dlPutSorted := dlPutPrev(L, DataRec);
  452.         end
  453.       else begin
  454.         dlPutSorted := dlAppend(L, DataRec);
  455.         end
  456.       end {if Less}
  457.     else begin
  458.       while dlGetPrev(L, DataRec0^) and not Less(DataRec0^, DataRec) do ;
  459.       if Less(DataRec0^, DataRec) then
  460.         dlPutSorted := dlPut(L, DataRec)
  461.       else
  462.         dlPutSorted := dlPush(L, DataRec);
  463.       end; {else}
  464.     FreeMemCheck(DataRec0, L.DataRecSize);
  465.     end; {dlPutSorted}
  466.  
  467. procedure slFree(var L : slList);
  468. {Releases the heap space allocated for a list and re-initializes the
  469.  list.}
  470.   var
  471.     T1  : LongInt;
  472.     P   : slNodePtr;
  473.   begin
  474.     for T1 := 1 to L.Count do begin
  475.       P := L.Head;
  476.       L.Head := P^.Next;
  477.       FreeMemCheck(P^.Data, L.DataRecSize);
  478.       FreeMemCheck(P, SizeOf(slNode));
  479.       end;
  480.     slListInit(L, L.DataRecSize);
  481.     end; {slFree}
  482.  
  483. procedure dlFree(var L : dlList);
  484. {Releases the heap space allocated for a list and re-initializes the
  485.  list.}
  486.   var
  487.     T1  : LongInt;
  488.     P   : dlNodePtr;
  489.   begin
  490.     for T1 := 1 to L.Count do begin
  491.       P := L.Head;
  492.       L.Head := P^.Next;
  493.       FreeMemCheck(P^.Data, L.DataRecSize);
  494.       FreeMemCheck(P, SizeOf(dlNode));
  495.       end;
  496.     dlListInit(L, L.DataRecSize);
  497.     end; {dlFree}
  498.  
  499. {******************RETRIEVAL ROUTINES************************}
  500.  
  501. function slGetCurrent(var L : slList; var DataRec) : boolean;
  502. {Returns the data record at the current node and does not move the node
  503.  pointer. Returns a function value of false if the list is empty or the
  504.  current node pointer is nil.}
  505.   begin
  506.     if L.Current = nil then begin
  507.       slGetCurrent := false;
  508.       exit;
  509.       end;
  510.     slGetCurrent := true;
  511.     Move(L.Current^.Data^, DataRec, L.DataRecSize);
  512.     end; {slGetCurrent}
  513.  
  514. function dlGetCurrent(var L : dlList; var DataRec) : boolean;
  515. {Returns the data record at the current node and does not move the node
  516.  pointer. Returns a function value of false if the list is empty or the
  517.  current node pointer is nil.}
  518.   var
  519.     S : slList absolute L;
  520.   begin
  521.     dlGetCurrent := slGetCurrent(S, DataRec);
  522.     end; {dlGetCurrent}
  523.  
  524. function slGetFirst(var L : slList; var DataRec) : boolean;
  525. {Returns the data record at the head of the list. Sets the current node
  526.  pointer to the head of the list. Returns a function value of false if
  527.  the list is empty.}
  528.   begin
  529.     L.Current := L.Head;
  530.     slGetFirst := slGetCurrent(L, DataRec);
  531.     end; {slGetFirst}
  532.  
  533. function dlGetFirst(var L : dlList; var DataRec) : boolean;
  534. {Returns the data record at the head of the list. Sets the current node
  535.  pointer to the head of the list. Returns a function value of false if
  536.  the list is empty.}
  537.   var
  538.     S : slList absolute L;
  539.   begin
  540.     dlGetFirst := slGetFirst(S, DataRec);
  541.     end; {dlGetFirst}
  542.  
  543. function slGetLast(var L : slList; var DataRec) : boolean;
  544. {Returns the data record at the tail of the list. Sets the current node
  545.  pointer to the tail of the list. Returns a function value of false if
  546.  the list is empty.}
  547.   begin
  548.     L.Current := L.Tail;
  549.     slGetLast := slGetCurrent(L, DataRec);
  550.     end; {slGetLast}
  551.  
  552. function dlGetLast(var L : dlList; var DataRec) : boolean;
  553. {Returns the data record at the tail of the list. Sets the current node
  554.  pointer to the tail of the list. Returns a function value of false if
  555.  the list is empty.}
  556.   var
  557.     S : slList absolute L;
  558.   begin
  559.     dlGetLast := slGetLast(S, DataRec);
  560.     end; {dlGetLast}
  561.  
  562. function slGetNext(var L :slList; var DataRec) : boolean;
  563. {Returns the next data record in the list. Sets the current node pointer
  564.  to the record retrieved. Returns a function value of false if the list is
  565.  empty or if the last record successfully retrieved was at the list tail.
  566.  In this case, calling slGetNext again will retrieve the head of the list.}
  567.   begin
  568.     if not (L.Count = 0) then begin
  569.       if L.Current = nil then
  570.         L.Current := L.Head
  571.       else
  572.         L.Current := L.Current^.Next;
  573.       end; {if not L.Count}
  574.     slGetNext := slGetCurrent(L, DataRec);
  575.     end; {slGetNext}
  576.  
  577. function dlGetNext(var L : dlList; var DataRec) : boolean;
  578. {Returns the next data record in the list. Sets the current node pointer
  579.  to the record retrieved. Returns a function value of false if the list is
  580.  empty or if the last record successfully retrieved was at the list tail.
  581.  In this case, calling dlGetNext again will retrieve the head of the list.}
  582.   var
  583.     S : slList absolute L;
  584.   begin
  585.     dlGetNext := slGetNext(S, DataRec);
  586.     end; {dlGetNext}
  587.  
  588. function dlGetPrev(var L : dlList; var DataRec) : boolean;
  589. {Same as dlGetNext, but in the opposite direction.}
  590.   begin
  591.     if not (L.Count = 0) then begin
  592.       if L.Current = nil then
  593.         L.Current := L.Tail
  594.       else
  595.         L.Current := L.Current^.Prev;
  596.       end; {if not L.Count}
  597.     dlGetPrev := dlGetCurrent(L, DataRec);
  598.     end; {dlGetPrev}
  599.  
  600. function slPop(var L : slList; var DataRec) : boolean;
  601. {Returns the data record at the head of the list, then deallocates the
  602.  space associated with the data record and node. Returns a function value
  603.  of false if the list is empty.}
  604.   var
  605.     P : slNodePtr;
  606.     B : boolean;
  607.   begin
  608.     B := slGetFirst(L, DataRec);
  609.     slPop := B;
  610.     if not B then exit;
  611.     P := L.Head;
  612.     L.Head := P^.Next;
  613.     L.Current := L.Head;
  614.     FreeMemCheck(P^.Data, L.DataRecSize);
  615.     FreeMemCheck(P, SizeOf(slNode));
  616.     dec(L.Count);
  617.     end; {slPop}
  618.  
  619. function dlPop(var L : dlList; var DataRec) : boolean;
  620. {Returns the data record at the head of the list, then deallocates the
  621.  space associated with the data record and node. Returns a function value
  622.  of false if the list is empty.}
  623.   var
  624.     P : dlNodePtr;
  625.     B : boolean;
  626.   begin
  627.     B := dlGetFirst(L, DataRec);
  628.     dlPop := B;
  629.     if not B then exit;
  630.     P := L.Head;
  631.     L.Head := P^.Next;
  632.     L.Head^.Prev := nil;
  633.     L.Current := L.Head;
  634.     FreeMemCheck(P^.Data, L.DataRecSize);
  635.     FreeMemCheck(P, SizeOf(dlNode));
  636.     dec(L.Count);
  637.     end; {dlPop}
  638.  
  639. {******************GENERAL UTILITY ROUTINES************************}
  640.  
  641. function slCount(L : slList) : LongInt;
  642. {Returns the number of records currently in the list.}
  643.   begin
  644.     slCount := L.Count;
  645.     end; {slCount}
  646.  
  647. function dlCount(L : dlList) : LongInt;
  648. {Returns the number of records currently in the list.}
  649.   begin
  650.     dlCount := L.Count;
  651.     end; {dlCount}
  652.  
  653. function slSpaceUsed(L : slList) : LongInt;
  654. {Returns the total amount of heap space currently allocated to the list.}
  655.   begin
  656.     slSpaceUsed := L.Count * (L.DataRecSize + SizeOf(slNode));
  657.     end; {slSpaceUsed}
  658.  
  659. function dlSpaceUsed(L : dlList) : LongInt;
  660. {Returns the total amount of heap space currently allocated to the list.}
  661.   begin
  662.     dlSpaceUsed := L.Count * (L.DataRecSize + SizeOf(dlNode));
  663.     end; {dlSpaceUsed}
  664.  
  665. end.
  666.